/*
 * 需要注意   (已经修改 默认携带请求头，想要不携带请求头token 你就true )
 * 本地有token 并且 请求头isToken等于true 则携带token
 *
 * 网络请求思路 => 生产的token令牌保存在cookie里   请求中需要token(令牌)则 带上cookie里的令牌
 * 也就是说 本地的cookie是用来存储令牌的而已  通信需要请求头中有令牌就行
 *
 * 是否需要防止数据重复提交 headers中 repeatSubmit 为 false 则需要防止重复提交, true则不需要防止
 *
 * 登录=》颁发token 使用时携带token
 */

import Vue from "vue";
import axios from "axios";

import store from "@/store";

import { getToken, setToken, removeToken } from "@/utils/token";
//错误代码
import errorCode from "@/utils/errorCode";
//好用的工具类
import { tansParams, blobValidate } from "@/utils/tool";

//若依本地存储操作
import cache from "@/utils/token";
//好用的下载
// import { saveAs } from "file-saver";
import router from "@/router";

import NProgress from "nprogress";

// 默认的请求地址
// axios.defaults.baseURL = 'http://127.0.0.1:3007/';
// 是否显示重新登录
// export let isRelogin = { show: false };
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";

const service = axios.create({
  // axios中请求配置有baseURL选项，表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 60000,
});

// 前置守卫 挂载token
service.interceptors.request.use(
  (config) => {
    NProgress.start();

    // 是否需要设置 token    headers中 isToken 为 false 则需要token, true则不需要token
    const isToken = !((config.headers || {}).isToken == true); //我自己改成true
    // 是否需要防止数据重复提交 headers中 repeatSubmit 为 false 则需要防止重复提交, true则不需要防止
    const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;

    //有token 并且 请求头需要token 则携带token
    if (getToken() && isToken) {
      config.headers["Authorization"] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
    }

    // get请求映射params参数
    if (config.method === "get" && config.params) {
      let url = config.url + "?" + tansParams(config.params);
      url = url.slice(0, -1);
      config.params = {};
      config.url = url;
    }

    //post 和 put 的请求防止刷新
    if (
      !isRepeatSubmit &&
      (config.method === "post" || config.method === "put")
    ) {
      //兼容数据 提交的是obj自动转换
      const requestObj = {
        url: config.url,
        data:
          typeof config.data === "object"
            ? JSON.stringify(config.data)
            : config.data,
        time: new Date().getTime(),
      };
      //如果sessionObj当前是空的 则写入当前的请求和数据进去，临时回话
      //如果不是空的 直接读取临时会话数据 和当前请求做对比
      const sessionObj = cache.session.getJSON("sessionObj");
      if (
        sessionObj === undefined ||
        sessionObj === null ||
        sessionObj === ""
      ) {
        cache.session.setJSON("sessionObj", requestObj);
      } else {
        //如果 会话中的data 等于当前的data 并且 会话的时间距离这次时间小于interval 并且 会话的请求地址等于当前请求地址
        const s_url = sessionObj.url; // 请求地址
        const s_data = sessionObj.data; // 请求数据
        const s_time = sessionObj.time; // 请求时间
        const interval = 1000; // 间隔时间(ms)，小于此时间视为重复提交
        if (
          s_data === requestObj.data &&
          requestObj.time - s_time < interval &&
          s_url === requestObj.url
        ) {
          const message = "数据正在处理，请勿重复提交";
          console.warn(`[${s_url}]: ` + message);
          return Promise.reject(new Error(message));
        } else {
          //否则不是频繁提交的话，保存本次请求到会话
          cache.session.setJSON("sessionObj", requestObj);
        }
      }
    }

    return config;
  },
  (error) => {
    console.log(error);
    Promise.reject(error);
  }
);

//后置守卫
service.interceptors.response.use(
  (config) => {
    NProgress.done();
    if (config.data.message == "身份认证失败！") {
      Vue.prototype.$message.error("身份过期啦！");
      setTimeout(() => {
        let temp = cache.local.getJSON("userinfo");
        temp.state = false;
        cache.local.setJSON("userinfo", temp);
        removeToken();
        router.go(0);
      }, 1000);
    }

    return config;
  },
  async function (error) {
    // 响应状态码4xx/5xx进这里
    // 对响应错误做点什么
    // console.dir(error)

    if (error.response.status === 401) {
      // 身份过期
      // token续签方式1:  去登录页重新登录, token无用, 清掉-确保路由守卫if进不去
      //提示过期
      Vue.prototype.$message.error("身份过期啦！");
      setTimeout(() => {
        let temp = cache.local.getJSON("userinfo");
        temp.state = false;
        cache.local.setJSON("userinfo", temp);
        removeToken();
        router.go(0);
      }, 1000);

      return;
      //
      // token续签方式2: refreshToken(用户无感知)
      // store.commit('setToken', '')
      // const res = await refreshTokenAPI()
      // store.commit('setToken', res.data.data.token)

      // 再调用一次未完成的请求啊(用户无感知)
      // error.config 就是上一次axios请求的配置对象
      // console.dir(error.config)
      // 把新的token赋予到下一次axios请求的请求头中
      // error.config.headers.Authorization = 'Bearer ' + res.data.data.token
      // return到await的地方
      // return axios(error.config)
    } else if (error.response.status === 500 && error.config.method === "put") {
      Vue.prototype.$message.error("身份过期啦！");
      setTimeout(() => {
        let temp = cache.local.getJSON("userinfo");
        temp.state = false;
        cache.local.setJSON("userinfo", temp);
        removeToken();
        router.go(0);
      }, 1000);

      // 都过期了
      // Notify('身份已过期')
      // router.replace({
      //     path: '/login'
      // })
      // router.replace({
      //     path: `/login?path=${router.currentRoute.fullPath}`
      // })
    } else {
      return Promise.reject(error);
    }
  }
);

//挂载
Vue.prototype.$http = service;

export default service;
